home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Environments / PowerMacOberon feb96 / Source / Dir.Mod (.txt) < prev    next >
Encoding:
Oberon Text  |  1995-10-17  |  20.5 KB  |  596 lines  |  [TEXT/.Ob4]

  1. Syntax10.Scn.Fnt
  2. StampElems
  3. Alloc
  4. 17 Oct 95
  5. VersionElems
  6. AllocBeg
  7. Syntax10.Scn.Fnt
  8. PowerMac
  9. WindowsPowerMac
  10. PowerMac
  11. Windows
  12. Syntax10.Scn.Fnt
  13. DELR = 0A1X; PageUp = 0C5X; PageDown = 0C6X;  Home = 0C8X; BRK = 0ACX;
  14. VersionElems
  15. AllocEnd
  16. Syntax10i.Scn.Fnt
  17. Syntax10b.Scn.Fnt
  18. FoldElems
  19. Syntax10i.Scn.Fnt
  20. forward declarations
  21. MarkElems
  22. Alloc
  23. Syntax10.Scn.Fnt
  24. PowerMac
  25. WindowsPowerMac
  26. PowerMac
  27. Windows
  28. Syntax10.Scn.Fnt
  29. MarkElems
  30. Alloc
  31. FoldElems
  32. Syntax10.Scn.Fnt
  33. BEGIN
  34.     IF name[0] # "&" THEN
  35.         Texts.WriteElem(w, NewElem(name, isDir)); Texts.WriteString(w, name); Texts.WriteLn(w)
  36. END MakeEntry;
  37. PROCEDURE 
  38. MakeEntry(name, dos: ARRAY OF CHAR; isDir: BOOLEAN);    
  39. Syntax10i.Scn.Fnt
  40. track mouse
  41. Syntax10i.Scn.Fnt
  42. open subdirectory
  43. Syntax10i.Scn.Fnt
  44. open file
  45. MODULE Dir;  (** HM 
  46. IMPORT Files, Fonts, Display, Input, Viewers, Texts, TextFrames, MenuViewers, Oberon, Directories, Strings, In, Out;
  47. CONST
  48. DELR = 008X; PageUp = 0ACX; PageDown = 0ADX;  Home = 091X; BRK = 0B9X;
  49.     delimiter = Directories.delimiter;
  50.     left =2; middle = 1; right = 0;
  51.     delete = 0; copy = 1; move = 2; select = 3; unselect = 4;    (*opcodes for ForAllElemsDo*)
  52.     pixel = LONG(10000);
  53.     CR = 0DX; DEL = 7FX; CRSU = 0C1X; CRSD = 0C2X;
  54.     Elem* = POINTER TO ElemDesc;
  55.     ElemDesc* = RECORD (Texts.ElemDesc)
  56.         name*: ARRAY 32 OF CHAR;
  57.         sel*: BOOLEAN;
  58.         icon, iconSel, iconCopy: Display.Pattern
  59.     END;
  60.     Text* = POINTER TO TextDesc;
  61.     TextDesc* = RECORD (Texts.TextDesc)
  62.         path*: ARRAY 128 OF CHAR
  63.     END;
  64.     UpdateMsg = RECORD (Display.FrameMsg)
  65.         op: INTEGER;
  66.         path, name: ARRAY 128 OF CHAR
  67.     END;
  68.     Opener = POINTER TO OpenerDesc;    (*list of commands to open files*)
  69.     OpenerDesc = RECORD
  70.         pattern, cmd: ARRAY 32 OF CHAR;
  71.         next: Opener
  72.     END;
  73.     scratch: Texts.Text;
  74.     invalidOp: BOOLEAN; (*TRUE if text operation suppressed in Notify*)
  75.     ignoreNeutralize: BOOLEAN;
  76.     w: Texts.Writer;
  77.     fileIcon, fileIconSel, fileIconCopy: Display.Pattern;  (*x=0, y=0, w=15, h=13*)
  78.     dirIcon, dirIconSel, dirIconCopy: Display.Pattern; (*x=0, y=0, w=15, h=13*)
  79.     copyHull, moveHull: Display.Pattern;
  80.     copyMarker, moveMarker: Oberon.Marker;
  81.     mask: ARRAY 32 OF CHAR;
  82.     openers: Opener;
  83. PROCEDURE ^ NoNotify (t: Texts.Text; op: INTEGER; beg, end: LONGINT);
  84. PROCEDURE ^ Notify (t: Texts.Text; op: INTEGER; beg, end: LONGINT);
  85. PROCEDURE ^ NotifyDir* (op: INTEGER; path, name: ARRAY OF CHAR);
  86. PROCEDURE ^ HandleElem* (e: Texts.Elem; VAR m: Texts.ElemMsg);
  87. PROCEDURE ^ HandleFrame*(f: Display.Frame; VAR m: Display.FrameMsg);
  88. PROCEDURE (e: Elem) 
  89. Update;    
  90.     VAR m: TextFrames.UpdateMsg;
  91. BEGIN
  92.     m.id := TextFrames.replace; m.text := Texts.ElemBase(e);
  93.     m.beg := Texts.ElemPos(e); m.end := m.beg + 1;
  94.     Viewers.Broadcast(m)
  95. END Update;
  96. PROCEDURE (e: Elem) 
  97. Restore;    
  98.     VAR r: Texts.Reader; t: Texts.Text; pos1, pos2: LONGINT;
  99. BEGIN
  100.     t := Texts.ElemBase(e); pos1 := Texts.ElemPos(e) + 1;
  101.     Texts.OpenReader(r, t, pos1); Texts.ReadElem(r);
  102.     IF r.eot THEN pos2 := t.len -1
  103.     ELSE pos2 := Texts.Pos(r) - 2
  104.     END;
  105.     Texts.Delete(t, pos1, pos2); Texts.WriteString(w, e.name); Texts.Insert(t, pos1, w.buf)
  106. END Restore;
  107. PROCEDURE (e: Elem) 
  108. Check;    
  109.     VAR s: Texts.Scanner; t: Texts.Text; old, new: ARRAY 256 OF CHAR;
  110.         res: INTEGER;
  111. BEGIN
  112.     t := Texts.ElemBase(e);
  113.     Texts.OpenScanner(s, t, Texts.ElemPos(e) + 1);
  114.     Texts.Scan(s);
  115.     IF (s.class = Texts.Name) & (s.line = 0) THEN
  116.         IF e.name # s.s THEN
  117.             COPY(t(Text).path, old); Strings.Append(delimiter, old); 
  118.             COPY(old, new);
  119.             Strings.Append(e.name, old);
  120.             Strings.Append(s.s, new);
  121.             Files.Rename(old, new, res);
  122.             IF res > 1 THEN Out.String("-- failed$"); e.Restore END
  123.         END
  124.     ELSE Out.String("-- failed$"); e.Restore
  125. END Check;
  126. PROCEDURE 
  127. Diff (VAR a, b: ARRAY OF CHAR): INTEGER;    
  128.     VAR i, d: INTEGER;
  129. BEGIN i := 0;
  130.     LOOP
  131.         IF CAP(a[i]) = CAP(b[i]) THEN
  132.             IF a[i] = 0X THEN d := 0; EXIT END
  133.         ELSIF CAP(a[i]) < CAP(b[i]) THEN d := -1; EXIT
  134.         ELSE d := 1; EXIT
  135.         END;
  136.         INC(i)
  137.     END;
  138.     RETURN d
  139. END Diff;
  140. PROCEDURE 
  141. NewElem (name: ARRAY OF CHAR; isDir: BOOLEAN): Elem;    
  142.     VAR e: Elem;
  143. BEGIN
  144.     NEW(e); e.W := 15 * pixel; e.H := 13 * pixel; e.handle := HandleElem; 
  145.     COPY(name, e.name); e.sel := FALSE;
  146.     IF isDir THEN e.icon := dirIcon; e.iconSel := dirIconSel; e.iconCopy := dirIconCopy
  147.     ELSE e.icon := fileIcon; e.iconSel := fileIconSel; e.iconCopy := fileIconCopy
  148.     END;
  149.     RETURN e
  150. END NewElem;
  151. PROCEDURE 
  152. ThisElem (t: Texts.Text; pos: LONGINT): Elem;    
  153.     VAR r: Texts.Reader; ch: CHAR;
  154. BEGIN
  155.     Texts.OpenReader(r, t, pos);  Texts.Read(r, ch);
  156.     IF ch # Texts.ElemChar THEN Texts.ReadPrevElem(r) END;
  157.     IF r.eot THEN RETURN NIL ELSE RETURN r.elem(Elem) END
  158. END ThisElem;
  159. PROCEDURE 
  160. FindElem (t: Texts.Text; name: ARRAY OF CHAR; VAR e: Elem; VAR pos: LONGINT; VAR d: INTEGER);    
  161.     VAR r: Texts.Reader;
  162. BEGIN
  163.     Texts.OpenReader(r, t, 0); Texts.ReadElem(r);
  164.     LOOP
  165.         IF r.eot THEN e := NIL; d := 1; pos := t.len; RETURN END;
  166.         IF r.elem IS Elem THEN
  167.             d := Diff(r.elem(Elem).name, name);
  168.             IF d >= 0 THEN e := r.elem(Elem); pos := Texts.ElemPos(e); EXIT END
  169.         END;
  170.         Texts.ReadElem(r)
  171. END FindElem;
  172. PROCEDURE 
  173. CopyFile (e:Elem; src, dst: Text);    
  174.     CONST bufSize = 4096;
  175.     VAR sn, dn: ARRAY 128 OF CHAR; sf, df: Files.File; sr, dr: Files.Rider;
  176.         len: LONGINT; buf: ARRAY bufSize OF CHAR;
  177. BEGIN
  178.     COPY(src.path, sn); Strings.Append(delimiter, sn); Strings.Append(e.name, sn);
  179.     COPY(dst.path, dn); Strings.Append(delimiter, dn); Strings.Append(e.name, dn);
  180.     sf := Files.Old(sn); Files.Set(sr, sf, 0);
  181.     df := Files.New(dn); Files.Set(dr, df, 0);
  182.     REPEAT
  183.         Files.ReadBytes(sr, buf, bufSize); Files.WriteBytes(dr, buf, bufSize - sr.res)
  184.     UNTIL sr.res # 0;
  185.     Files.Register(df)
  186. END CopyFile;
  187. PROCEDURE 
  188. MoveFile (e:Elem; src, dst: Text);    
  189.     VAR sn, dn: ARRAY 256 OF CHAR; res: INTEGER;
  190. BEGIN
  191.     COPY(src.path, sn); Strings.Append(delimiter, sn); Strings.Append(e.name, sn);
  192.     COPY(dst.path, dn); Strings.Append(delimiter, dn); Strings.Append(e.name, dn);
  193.     Files.Rename(sn, dn, res)
  194. END MoveFile;
  195. PROCEDURE 
  196. MakeEntry(d: Directories.Directory; name: ARRAY OF CHAR; isDir: BOOLEAN; VAR continue: BOOLEAN);    
  197. BEGIN
  198.     Texts.WriteElem(w, NewElem(name, isDir)); Texts.WriteString(w, name); Texts.WriteLn(w)
  199. END MakeEntry;
  200. PROCEDURE 
  201. OpenDir (d: Directories.Directory);    
  202.     VAR t: Text; f: TextFrames.Frame; x, y: INTEGER; v: Viewers.Viewer;
  203. BEGIN
  204.     Directories.Enumerate(d, MakeEntry);
  205.     NEW(t); Texts.Open(t, ""); COPY(d.path, t.path);
  206.     t.notify := NoNotify; Texts.Append(t, w.buf); t.notify := Notify;
  207.     NEW(f); TextFrames.Open(f, t, 0); f.handle := HandleFrame;
  208.     Oberon.AllocateSystemViewer(0, x, y);
  209.     v := MenuViewers.New(
  210.         TextFrames.NewMenu(d.path, "^Dir.Menu.Text"),
  211.         f, TextFrames.menuH, x, y)
  212. END OpenDir;
  213. PROCEDURE 
  214. ForAllElemsDo (op: INTEGER; src, dst: Text);    
  215.     VAR r: Texts.Reader; beg, end: LONGINT; f: TextFrames.Frame; e: Elem; path: ARRAY 256 OF CHAR; res: INTEGER;
  216. BEGIN
  217.     IF src = NIL THEN RETURN END;
  218.     end := src.len; Texts.OpenReader(r, src, end);
  219.     LOOP
  220.         Texts.ReadPrevElem(r); IF r.eot THEN EXIT END;
  221.         IF r.elem IS Elem THEN
  222.             e := r.elem(Elem); beg := Texts.Pos(r);
  223.             IF e.sel THEN
  224.                 IF op = delete THEN
  225.                     COPY(src.path, path); Strings.Append(delimiter, path); Strings.Append(e.name, path);
  226.                     Files.Delete(path, res);
  227.                     IF res # 0 THEN Out.String("-- failed$") END
  228.                 ELSIF op = copy THEN
  229.                     CopyFile(e, src, dst);
  230.                     e.sel := FALSE; e.Update
  231.                 ELSIF op = move THEN
  232.                     MoveFile(e, src, dst);
  233.                 ELSIF op = unselect THEN
  234.                     e.sel := FALSE; e.Update
  235.                 END;
  236.                 Texts.OpenReader(r, src, beg)
  237.             ELSIF (op = select) & Strings.Match(e.name, mask) THEN
  238.                 e.sel := TRUE; e.Update
  239.             END;
  240.             end := beg
  241.         END
  242. END ForAllElemsDo;
  243. PROCEDURE 
  244. DrawCopy (x, y: INTEGER);    
  245. BEGIN
  246.     Display.CopyPattern(Display.white, copyHull, x, y, Display.invert)
  247. END DrawCopy;
  248. PROCEDURE 
  249. DrawMove (x, y: INTEGER);    
  250. BEGIN
  251.     Display.CopyPattern(Display.white, moveHull, x, y, Display.invert)
  252. END DrawMove;
  253. PROCEDURE 
  254. ThisFrame (x, y: INTEGER): TextFrames.Frame;    
  255.     VAR v: Viewers.Viewer; f: Display.Frame;
  256. BEGIN
  257.     v := Viewers.This(x, y); f := v.dsc;
  258.     WHILE (f # NIL) 
  259.     & ((x < f.X) OR (x > f.X+f.W) OR (y < f.Y) OR (y > f.Y+f.H)) DO
  260.         f := f.next
  261.     END;
  262.     IF f IS TextFrames.Frame THEN RETURN f(TextFrames.Frame)
  263.     ELSE RETURN NIL
  264. END ThisFrame;
  265. PROCEDURE 
  266. TargetText(): Text;    
  267.     VAR f: TextFrames.Frame;
  268. BEGIN
  269.     IF Oberon.Par.frame = Oberon.Par.vwr.dsc THEN
  270.         f := Oberon.Par.frame.next(TextFrames.Frame)
  271.     ELSE
  272.         f := ThisFrame(Oberon.Pointer.X, Oberon.Pointer.Y);
  273.     END;
  274.     IF f.text IS Text THEN RETURN f.text(Text) ELSE RETURN NIL END
  275. END TargetText;
  276. PROCEDURE 
  277. Init;    
  278.     VAR line: ARRAY 14 OF SET; s: Texts.Scanner; x: Opener;
  279. BEGIN
  280.     line[1] := {};
  281.     line[2] := {1..8};
  282.     line[3] := {1, 8};
  283.     line[4] := {1, 8};
  284.     line[5] := {1, 8};
  285.     line[6] := {1, 8};
  286.     line[7] := {1, 8};
  287.     line[8] := {1, 8};
  288.     line[9] := {1, 5..8};
  289.     line[10] := {1, 5, 7};
  290.     line[11] := {1, 5, 6};
  291.     line[12] := {1..5};
  292.     line[13] := {};
  293.     fileIcon := Display.NewPattern(line, 15, 13);
  294.     line[1] := {};
  295.     line[2] := {1..8};
  296.     line[3] := {1, 4, 8};
  297.     line[4] := {1, 4, 8};
  298.     line[5] := {1, 2..6, 8};
  299.     line[6] := {1, 4, 8};
  300.     line[7] := {1, 4, 8};
  301.     line[8] := {1, 8};
  302.     line[9] := {1, 5..8};
  303.     line[10] := {1, 5, 7};
  304.     line[11] := {1, 5, 6};
  305.     line[12] := {1..5};
  306.     line[13] := {};
  307.     fileIconCopy := Display.NewPattern(line, 15, 13);
  308.     line[1] := {};
  309.     line[2] := {1..8};
  310.     line[3] := {1..8};
  311.     line[4] := {1..8};
  312.     line[5] := {1..8};
  313.     line[6] := {1..8};
  314.     line[7] := {1..8};
  315.     line[8] := {1..8};
  316.     line[9] := {1..8};
  317.     line[10] := {1..5, 7};
  318.     line[11] := {1..6};
  319.     line[12] := {1..5};
  320.     line[13] := {};
  321.     fileIconSel := Display.NewPattern(line, 15, 13);
  322.     line[1] := {};
  323.     line[2] := {};
  324.     line[3] := {1..10};
  325.     line[4] := {1, 10};
  326.     line[5] := {1, 10};
  327.     line[6] := {1, 10};
  328.     line[7] := {1, 10};
  329.     line[8] := {1, 10};
  330.     line[9] := {1, 10};
  331.     line[10] := {1..10};
  332.     line[11] := {1, 5};
  333.     line[12] := {1..4};
  334.     line[13] := {};
  335.     dirIcon := Display.NewPattern(line, 15, 13);
  336.     line[1] := {};
  337.     line[2] := {};
  338.     line[3] := {1..10};
  339.     line[4] := {1, 6, 10};
  340.     line[5] := {1, 6, 10};
  341.     line[6] := {1, 4..8, 10};
  342.     line[7] := {1, 6, 10};
  343.     line[8] := {1, 6, 10};
  344.     line[9] := {1, 10};
  345.     line[10] := {1..10};
  346.     line[11] := {1, 5};
  347.     line[12] := {1..4};
  348.     line[13] := {};
  349.     dirIconCopy := Display.NewPattern(line, 15, 13);
  350.     line[1] := {};
  351.     line[2] := {};
  352.     line[3] := {1..10};
  353.     line[4] := {1..10};
  354.     line[5] := {1..10};
  355.     line[6] := {1..10};
  356.     line[7] := {1..10};
  357.     line[8] := {1..10};
  358.     line[9] := {1..10};
  359.     line[10] := {1..10};
  360.     line[11] := {1, 5};
  361.     line[12] := {1..4};
  362.     line[13] := {};
  363.     dirIconSel := Display.NewPattern(line, 15, 13);
  364.     copyMarker.Draw := DrawCopy; copyMarker.Fade := DrawCopy;
  365.     moveMarker.Draw := DrawMove; moveMarker.Fade := DrawMove;
  366.     Texts.OpenWriter(w);
  367.     ignoreNeutralize := FALSE;
  368.     Directories.notify := NotifyDir;
  369.     NEW(scratch); Texts.Open(scratch, "Dir.Menu.Text"); scratch.notify := NoNotify;
  370.     Texts.OpenScanner(s, scratch, 0); openers := NIL;
  371.     REPEAT Texts.Scan(s) UNTIL s.eot OR (s.line # 0);
  372.     WHILE s.class = Texts.String DO
  373.         NEW(x); COPY(s.s, x.pattern); Texts.Scan(s);
  374.         IF s.class IN {Texts.Name, Texts.String} THEN COPY(s.s, x.cmd); Texts.Scan(s); x.next := openers; openers := x END
  375. END Init;
  376. PROCEDURE 
  377. NoNotify (t: Texts.Text; op: INTEGER; beg, end: LONGINT);    
  378. END NoNotify;
  379. PROCEDURE 
  380. Notify (t: Texts.Text; op: INTEGER; beg, end: LONGINT);    
  381.     VAR b: Texts.Buffer; r: Texts.Reader; ch: CHAR; pos: LONGINT;
  382. BEGIN
  383.     IF op = TextFrames.delete THEN
  384.         pos := scratch.len; Texts.Recall(b); Texts.Append(scratch, b);
  385.         Texts.OpenReader(r, scratch, pos);
  386.         REPEAT
  387.             Texts.Read(r, ch)
  388.         UNTIL r.eot OR (ch = CR) OR (ch = Texts.ElemChar) & (r.elem IS Elem);
  389.         IF ~r.eot THEN
  390.             invalidOp := TRUE;
  391.             t.notify := NoNotify;
  392.             Texts.Save(scratch, pos, t.len, b);
  393.             Texts.Insert(t, beg, b);
  394.             t.notify := Notify;
  395.             op := TextFrames.replace; end := beg
  396.         END
  397.     ELSIF op = TextFrames.insert THEN
  398.         Texts.OpenReader(r, t, beg); pos := beg;
  399.         REPEAT
  400.             Texts.Read(r, ch); INC(pos)
  401.         UNTIL (pos > end) OR (ch = CR) 
  402.         OR (ch = Texts.ElemChar) & (r.elem IS Elem);
  403.         IF pos <= end THEN
  404.             invalidOp := TRUE;
  405.             t.notify := NoNotify;
  406.             Texts.Delete(t, beg, end);
  407.             t.notify := Notify;
  408.             op := TextFrames.replace; end := beg
  409.         END
  410.     END;
  411.     ignoreNeutralize := TRUE;
  412.     TextFrames.NotifyDisplay(t, op, beg, end);
  413.     ignoreNeutralize := FALSE
  414. END Notify;
  415. PROCEDURE 
  416. NotifyDir* (op: INTEGER; path, name: ARRAY OF CHAR);    
  417.     VAR m: UpdateMsg;
  418. BEGIN
  419.     m.op := op; COPY(path, m.path); COPY(name, m.name);
  420.     Viewers.Broadcast(m)
  421. END NotifyDir;
  422. PROCEDURE 
  423. HandleElem* (e: Texts.Elem; VAR m: Texts.ElemMsg);    
  424.     CONST moved = -1000;
  425.     VAR e1: Elem; x, y, x0, y0, dsr, res: INTEGER; keys: SET; t: Texts.Text;
  426.         path: ARRAY 128 OF CHAR; marker: Oberon.Marker;
  427.         f: TextFrames.Frame; src, dst: Text; d: Directories.Directory; name: ARRAY 256 OF CHAR; o: Opener;
  428. BEGIN
  429.     WITH e: Elem DO
  430.         WITH m: Texts.CopyMsg DO
  431.             IF m.e = NIL THEN NEW(e1); m.e := e1 ELSE e1 := m.e(Elem) END;
  432.             Texts.CopyElem(e, e1);
  433.             COPY(e.name, e1.name);
  434.             e1.sel := e.sel; e1.icon := e.icon; e1.iconSel := e.iconSel; e1.iconCopy := e.iconCopy
  435.         | m: TextFrames.DisplayMsg DO
  436.             IF ~m.prepare THEN
  437.                 IF e.sel THEN
  438.                     Display.CopyPattern(Display.white, e.iconSel, m.X0, m.Y0+1, Display.replace)
  439.                 ELSE
  440.                     Display.CopyPattern(Display.white, e.icon, m.X0, m.Y0+1, Display.replace)
  441.                 END
  442.             END
  443.         | m: TextFrames.TrackMsg DO
  444.                 IF middle IN m.keys THEN
  445.                     e.sel := ~e.sel; e.Update;
  446.                     src := m.frame(TextFrames.Frame).text(Text);
  447.                     
  448. Input.Mouse(keys, x0, y0);
  449.                     marker := Oberon.Arrow; copyHull := e.iconCopy; moveHull := e.icon;
  450.                     REPEAT Input.Mouse(keys, x, y); m.keys := m.keys + keys;
  451.                         IF (e.icon # dirIcon) & ((ABS(x-x0) > 10) OR (ABS(y-y0) > 10)) THEN
  452.                             x0 := moved;
  453.                             IF m.keys = {middle, left} THEN marker := copyMarker ELSE marker := moveMarker END
  454.                         END;
  455.                         Oberon.DrawCursor(Oberon.Mouse, marker, x, y)
  456.                     UNTIL keys = {};
  457.                     IF m.keys = {middle, right} THEN
  458.                         IF e.icon = dirIcon THEN
  459.                             
  460. t := Texts.ElemBase(e);
  461.                             COPY(t(Text).path, path); Strings.Append(delimiter, path); Strings.Append(e.name, path);
  462.                             OpenDir(Directories.This(path))
  463.                         ELSE
  464.                             
  465. d := Directories.Current(); name := "";
  466.                             IF src.path # d.path THEN
  467.                                 Strings.Append(src.path, name); Strings.Append(delimiter, name)
  468.                             END;
  469.                             Strings.Append(e.name, name);
  470.                             o := openers;
  471.                             WHILE (o # NIL) & ~Strings.Match(e.name, o.pattern) DO o := o.next END;
  472.                             IF o = NIL THEN NEW(o); o.cmd := "Edit.Open" END;
  473.                             Oberon.Par.vwr := Viewers.This(m.X, m.Y); Oberon.Par.frame := m.frame;
  474.                             Oberon.Par.pos := scratch.len; Oberon.Par.text := scratch;
  475.                             Texts.WriteString(w, name); Texts.Append(scratch, w.buf);
  476.                             Oberon.Call(o.cmd, Oberon.Par, FALSE, res)
  477.                         END;
  478.                         e.sel := FALSE; e.Update
  479.                     ELSIF (x0 = moved) & e.sel THEN
  480.                         f := ThisFrame(x, y);
  481.                         IF (f # NIL) & (f # m.frame) & (f.text IS Text) THEN
  482.                             dst := f.text(Text);
  483.                             IF m.keys = {middle} THEN
  484.                                 ForAllElemsDo(move, src, dst)
  485.                             ELSIF m.keys = {middle, left} THEN
  486.                                 ForAllElemsDo(copy, src, dst)
  487.                             END
  488.                         END
  489.                     END
  490.                 END
  491.         ELSE
  492.         END
  493. END HandleElem;
  494. PROCEDURE 
  495. HandleFrame* (f: Display.Frame; VAR m: Display.FrameMsg);    
  496.     VAR ready: BOOLEAN; e: Elem; keys: SET; x, y, d: INTEGER; t: Texts.Text;
  497.         pos, pos2: LONGINT; r: Texts.Reader; ch: CHAR; path: ARRAY 256 OF CHAR; dir: Directories.Directory;
  498. BEGIN
  499.     ready := FALSE;
  500.     WITH f: TextFrames.Frame DO
  501.         WITH m: Oberon.InputMsg DO
  502.             IF m.id = Oberon.consume THEN
  503.                 pos := f.carloc.pos; e := ThisElem(f.text, pos);
  504.                 IF (m.ch = CR) OR (m.ch = PageUp) OR (m.ch = PageDown) OR (m.ch = Home) OR (m.ch = BRK) THEN
  505.                     e.Check; TextFrames.RemoveCaret(f); ready := TRUE
  506.                 ELSIF (m.ch = CRSU) OR (m.ch = CRSD) THEN
  507.                     e.Check
  508.                 ELSIF m.ch = DEL THEN
  509.                     invalidOp := FALSE;
  510.                     TextFrames.Handle(f, m); ready := TRUE;
  511.                     IF invalidOp THEN
  512.                         e := ThisElem(f.text, pos);
  513.                         e.Check; TextFrames.RemoveCaret(f)
  514.                     END
  515.                 ELSE
  516.                     Texts.OpenReader(r, f.text, f.carloc.pos); Texts.Read(r, ch);
  517.                     ready := (ch = Texts.ElemChar) & (r.elem IS Elem)
  518.                 END
  519.             ELSIF (m.id = Oberon.track) & f.hasCar & (m.keys * {middle, right} # {}) THEN
  520.                 e := ThisElem(f.text, f.carloc.pos);
  521.                 IF (e # NIL) & (ThisElem(f.text, TextFrames.Pos(f, x, y)) # e) THEN e.Check END
  522.             END
  523.         | m: Oberon.ControlMsg DO
  524.             IF m.id = Oberon.defocus THEN
  525.                 e := ThisElem(f.text, f.carloc.pos);
  526.                 Input.Mouse(keys, x, y);
  527.                 IF (e # NIL) & ((f # ThisFrame(x, y)) OR (ThisElem(f.text, TextFrames.Pos(f, x, y)) # e)) THEN
  528.                     e.Check
  529.                 END
  530.             ELSIF (m.id = Oberon.neutralize) & ~ignoreNeutralize & f.hasCar THEN
  531.                 e := ThisElem(f.text, f.carloc.pos);
  532.                 IF e # NIL THEN e.Check END
  533.             END
  534.         | m: UpdateMsg DO
  535.             IF f.text(Text).path = m.path THEN
  536.                 t := f.text; FindElem(t, m.name, e, pos, d);
  537.                 t.notify := TextFrames.NotifyDisplay; 
  538.                 CASE m.op OF
  539.                    Directories.insert:
  540.                     IF d # 0 THEN
  541.                         COPY(m.path, path); Strings.Append(delimiter, path); Strings.Append(m.name, path);
  542.                         dir := Directories.This(path);
  543.                         Texts.WriteElem(w, NewElem(m.name, dir # NIL)); Texts.WriteString(w, m.name); Texts.WriteLn(w);
  544.                         Texts.Insert(t, pos, w.buf)
  545.                     END
  546.                 | Directories.delete:
  547.                     IF d = 0 THEN
  548.                         Texts.OpenReader(r, t, pos+1); Texts.ReadElem(r);
  549.                         IF r.eot THEN pos2 := t.len ELSE pos2 := Texts.Pos(r) - 1 END;
  550.                         Texts.Delete(t, pos, pos2)
  551.                     END
  552.                 END;
  553.                 t.notify := Notify
  554.             END
  555.         ELSE
  556.         END
  557.     END;
  558.     IF ~ready THEN TextFrames.Handle(f, m) END
  559. END HandleFrame;
  560. PROCEDURE 
  561. Open*;    
  562. BEGIN
  563.     OpenDir(Directories.Current())
  564. END Open;
  565. PROCEDURE 
  566. New*;    
  567.     VAR name: ARRAY 256 OF CHAR; i: INTEGER;
  568. BEGIN
  569.     In.Open;
  570.     IF In.Next() = In.string THEN In.String(name) ELSE In.Name(name) END;
  571.     IF In.Done THEN Directories.Create(name) END
  572. END New;
  573. PROCEDURE 
  574. Delete*;    
  575. BEGIN
  576.     ForAllElemsDo(delete, TargetText(), NIL)
  577. END Delete;
  578. PROCEDURE 
  579. Select*;    
  580.     VAR ch: CHAR; i: INTEGER;
  581. BEGIN
  582.     In.Open; i := 0;
  583.     REPEAT In.Char(ch) UNTIL ch >= " ";
  584.     REPEAT mask[i] := ch; INC(i); In.Char(ch) UNTIL (ch <= " ") OR (ch > 7FX);
  585.     mask[i] := 0X;
  586.     ForAllElemsDo(select, TargetText(), NIL)
  587. END Select;
  588. PROCEDURE 
  589. Deselect*;    
  590. BEGIN
  591.     ForAllElemsDo(unselect, TargetText(), NIL)
  592. END Deselect;
  593. BEGIN
  594.     Init
  595. END Dir.
  596.